#ifndef __M_QUEUE_H__
#define __M_QUEUE_H__
#include "../mqcommon/helper.hpp"
#include "../mqcommon/log.hpp"
#include "../mqcommon/mq_meg.pb.h"

#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>
#include <vector>
#include <cassert>

namespace pprmq
{
    class MsgQueue
    {
    public:
        using ptr = std::shared_ptr<MsgQueue>;
        MsgQueue() {}

        MsgQueue(std::string name, bool durable, bool exclusive, bool auto_delete,
                const google::protobuf::Map<std::string, std::string> args)
            : _name(name), _durable(durable), _exclusive(exclusive),
              _auto_delete(auto_delete), _args(args)
        {
        }

        // "key=val&key=val"--->存入args中
        void setArgs(const std::string &str_args)
        {
            // 以&为分割符，将分割开的数据存放到result中
            std::vector<std::string> result;
            pprmq::StrHelper::split(str_args, "&", result);
            for (auto &str : result)
            {
                size_t pos = str.find("=");
                std::string key = str.substr(0, pos);
                std::string value = str.substr(pos + 1);
                _args[key] = value;
            }
        }

        // 从args中拿出数据，转化为字符串
        std::string getArgs()
        {
            std::string result;
            for (auto &[key, val] : _args)
            {
                result += key + "=" + val + "&";
            }
            return result;
        }

    public:
        std::string _name;
        bool _durable; // 持久化
        bool _exclusive; // 是否独占
        bool _auto_delete; // 自动删除标志
        google::protobuf::Map<std::string, std::string> _args;
    };

    using QueueMap = std::unordered_map<std::string, MsgQueue::ptr>;
    class MsgQueueMapper
    {
    public:
        MsgQueueMapper(std::string dbfile) : _sql_helper(dbfile)
        {
            // 获取文件父目录
            std::string path = pprmq::FileHelper::parentDirectory(dbfile);
            // 创建文件
            pprmq::FileHelper::createDirectory(path); // 确保目录存在
            // 打开数据库
            assert(_sql_helper.open());
            // 创建队列表
            createTable();
        }

        void createTable()
        {
            // create table if not exists queue_table(...);
            std::stringstream sql;
            sql << "create table if not exists queue_table(";
            sql << "name varchar(32),";
            sql << "durable int,";
            sql << "exclusive int,";
            sql << "auto_delete int,";
            sql << "args varchar(128));";
            _sql_helper.exec(sql.str(), nullptr, nullptr);
        }

        void removeTable()
        {
            std::string sql = "drop table if exists queue_table;";
            _sql_helper.exec(sql, nullptr, nullptr);
        }

        bool insert(MsgQueue::ptr &exp)
        {
            std::stringstream ss;
            ss << "insert into queue_table values(";
            ss << "'" << exp->_name << "',";
            ss << exp->_durable << ",";
            ss << exp->_exclusive << ",";
            ss << exp->_auto_delete << ",";
            ss << "'" << exp->getArgs() << "');";
            return _sql_helper.exec(ss.str(), nullptr, nullptr);
        }
        void remove(const std::string &name)
        {
            std::stringstream sql;
            sql << "delete from queue_table where name=";
            sql << "'" << name << "';";
            _sql_helper.exec(sql.str(), nullptr, nullptr);
        }

        QueueMap recovery()
        {
            QueueMap result;
            std::stringstream sql;
            sql << "select name,durable,exclusive,auto_delete,args from queue_table;";
            _sql_helper.exec(sql.str(), SelectCallback, &result);
            return result;
        }

    private:
        static int SelectCallback(void *args, int col, char **row, char **fields)
        {
            QueueMap *result = (QueueMap *)args;
            MsgQueue::ptr mqp = std::make_shared<MsgQueue>();
            mqp->_name = row[0];
            mqp->_durable = (bool)std::stoi(row[1]);
            mqp->_exclusive = (bool)std::stoi(row[2]);
            mqp->_auto_delete = (bool)std::stoi(row[3]);
            if (row[4])
                mqp->setArgs(row[4]);
            result->insert(std::make_pair(mqp->_name, mqp));
            return 0;
        }

    private:
        Sqlitehelper _sql_helper;
    };

    class QueueManager
    {
    public:
        using ptr = std::shared_ptr<QueueManager>;
        QueueManager(const std::string &dbfile)
            : _mapper(dbfile)
        {
            _msg_queues = _mapper.recovery();
        }

        // 声明队列，如果有就OK，没有就创建
        bool declareQueue(const std::string &qname, 
                bool qdurable, 
                bool qexclusive,
                bool qauto_delete,
                const google::protobuf::Map<std::string, std::string> &qargs)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _msg_queues.find(qname);
            if(it != _msg_queues.end())
            {
                // 找到了，不需要创建直接返回
                return true;
            }
            // 没找到，创建队列
            auto mqp = std::make_shared<MsgQueue>(qname,qdurable,qexclusive,qauto_delete,qargs);

            // auto mqp = std::make_shared<MsgQueue>();
            // mqp->_name = qname;
            // mqp->_durable = qdurable;
            // mqp->_exclusive = qexclusive;
            // mqp->_auto_delete = qauto_delete;
            // mqp->_args = qargs;

            if(qdurable == true)
            {
                bool ret = _mapper.insert(mqp);
                if(ret == false) return false;
            }
            _msg_queues.insert(std::make_pair(qname,mqp));
            return true;
        }
        // 删除队列
        void deleteMsgQueue(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _msg_queues.find(name);
            if (it == _msg_queues.end())
            {
                // 队列不存在，不需要删除，直接返回
                return;
            }
            // 如果有数据持久化，就需要将数据库中的数据清理
            if (it->second->_durable == true)
                _mapper.remove(name);
            _msg_queues.erase(name);
        }
        // 获取指定交换机对象
        MsgQueue::ptr selectMsgQueue(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _msg_queues.find(name);
            if (it != _msg_queues.end())
            {
                // 找到了
                return it->second;
            }
            return MsgQueue::ptr();
        }
        // 返回内存中交换机的总数（用于监控或统计）
        size_t size()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _msg_queues.size();
        }

        QueueMap allQueues()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _msg_queues;
        }

        // 判断交换机是否存在
        bool exists(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _msg_queues.find(name);
            if (it != _msg_queues.end())
            {
                return true;
            }
            return false;
        }
        // 清理所有交换机数据
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _mapper.removeTable();
            _msg_queues.clear();
        }

    private:
        std::mutex _mutex;
        MsgQueueMapper _mapper; // 持久化管理器，与数据库交互的桥梁
        QueueMap _msg_queues;   // 内存交换机存储（哈希表，key=交换机名称，value=智能指针）
    };
}
#endif